package com.pubsys.main.server.rpc.referenciaservice;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import com.pubsys.main.client.rpc.referenciaservice.ReferenciaService;
import com.pubsys.main.server.database.Database;
import com.pubsys.main.server.rpc.SisWebRemoteServiceServlet;
import com.pubsys.main.shared.exceptions.RPCExceptions;
import com.pubsys.main.shared.model.Autor;
import com.pubsys.main.shared.model.FiltroReferencia;
import com.pubsys.main.shared.model.Referencia;

public class ReferenciaServiceImpl extends SisWebRemoteServiceServlet implements
		ReferenciaService {
	private static SimpleDateFormat dateFormatter = new SimpleDateFormat(
			"yyyy-MM-dd");
	/**
	 * 
	 */
	private static final long serialVersionUID = -809748370884849479L;

	// private static final Logger LOG = Logger
	// .getLogger(ReferenciaServiceImpl.class.getName());
	// private static final PersistenceManagerFactory PMF = JDOHelper
	// .getPersistenceManagerFactory("transactions-optional");

	/*
	 * Adiciona uma referência
	 */
	public void addReferencia(Referencia referencia) throws RPCExceptions {

		String values = "";
		String fields = "";
		String table = " \"referencias\" ";

		
		//da lista de autores dessa referencia, verifica se o autor logado se inclui na lista.
		boolean achou = false;
		for (Autor autor : referencia.getAutores()) {
			if (autor.getNome().equals(this.getLoggedUser().getNome())){
				achou = true;
				break;
			}
		}
		//se nao, adiciona ele proprio na lista
		if (!achou)
			referencia.addAutor(this.getLoggedUser());
		
		
		String virgula = "";
		if (referencia.getTitulo() != null
				&& !referencia.getTitulo().trim().equals("")) {
			fields += virgula + " \"titulo\"";
			values += virgula + " '" + referencia.getTitulo() + "'";
			virgula = ", ";
		}
		if (referencia.getCodigo() != null
				&& !referencia.getCodigo().trim().equals("")) {
			fields += virgula + " \"codigo\"";
			values += virgula + " '" + referencia.getCodigo() + "'";
			virgula = ", ";
		}
		if (referencia.getEditora() != null
				&& !referencia.getEditora().trim().equals("")) {
			fields += virgula + " \"editora\"";
			values += virgula + " '" + referencia.getEditora() + "'";
			virgula = ", ";
		}
		if (referencia.getLocal() != null
				&& !referencia.getLocal().trim().equals("")) {
			fields += virgula + " \"local\"";
			values += virgula + " '" + referencia.getLocal() + "'";
			virgula = ", ";
		}
		if (referencia.getDataPub() != null) {

			fields += virgula + " \"datapub\"";
			values += virgula + " '"
					+ dateFormatter.format(referencia.getDataPub()) + "'";
			virgula = ", ";
		}

		
		try {
			// salva as referencias
			int idReferencia = Database.getDatabaseInstance().insert(table,
					fields, values, "id");
			referencia.setId(idReferencia);
			// salva os autores
			this.salvaAutores(referencia);
		} catch (SQLException e) {
			throw new RPCExceptions(e.getMessage());
		}

	}

	/*
	 * Retorna uma lista de referências de acordo com o filtro passado como
	 * parametro
	 */
	public List<Referencia> getReferencias(FiltroReferencia filter) {
		LinkedList<Referencia> referencias = new LinkedList<Referencia>();


//		SimpleDateFormat formatador = new SimpleDateFormat("MM/dd/yyyy");

		try {
			String select = "select * from \"autores_referencias\" ";
			String filtro = "where ";

			if (filter.getIdReferencia() != null) {
				filtro = filtro.concat("id = '"
						+ filter.getIdReferencia().toString() + "'");
			}
			

			if (filter.getDateAfter() != null) {
				if (filtro.length() > 6)
					filtro = filtro.concat(" and datapub > '"
							+ dateFormatter.format(filter.getDateBefore()) + "'");
				else
					filtro = filtro.concat("datapub > '"
							+ dateFormatter.format(filter.getDateBefore()) + "'");
			}
			
			String autores = "";
			if (filter.getAutores() != null) {
				String and = "";
				for (Autor autor : filter.getAutores()) {
					autores += and + " \"nome\" LIKE '%" + autor.getNome() + "%' ";					
					and = " and ";						
				}		
				
				if (filtro.length() > 6)
					filtro = filtro.concat(" and " + autores);
				else
					filtro = filtro.concat(autores);
			}
			
			
			if (filter.getLocal() != null && !filter.getLocal().isEmpty()) {
				if (filtro.length() > 6)
					filtro = filtro.concat(" and local = '" + filter.getLocal()
							+ "'");
				else
					filtro = filtro.concat("local = '" + filter.getLocal()
							+ "'");
			}
			if (filter.getTitulo() != null && !filter.getTitulo().isEmpty()) {
				if (filtro.length() > 6)
					filtro.concat(" and titulo = '" + filter.getTitulo() + "'");
				else
					filtro = filtro.concat("titulo = '" + filter.getTitulo()
							+ "'");
			}
			
			if (filter.getEditora() != null && !filter.getEditora().isEmpty()) {
				if (filtro.length() > 6)
					filtro.concat(" and editora = '" + filter.getEditora() + "'");
				else
					filtro = filtro.concat("editora = '" + filter.getEditora()
							+ "'");
			}
			

			if (filtro.length() > 6)
				select = select.concat(filtro);

			ResultSet res = Database.getDatabaseInstance().doSelect(select);

			Referencia referencia;
			Integer oldReference = -1;
			while (res.next()) {
				
				Integer idReferencia = res.getInt("id_referencia");
			
				if (oldReference != idReferencia){

					oldReference = idReferencia;
					
					referencia = new Referencia();
					referencia.setId(idReferencia);						
					referencia.setTitulo(res.getString("titulo"));
					referencia.setDataPub(res.getDate("datapub"));
					referencia.setCodigo(res.getString("codigo"));
					referencia.setEditora(res.getString("editora"));
					referencia.setLocal(res.getString("local"));
					
					referencia.setAutores(getReferenceAuthors(idReferencia));
					
					referencias.add(referencia);
				}
				
					

			}

		} catch (Exception e) {
			e.printStackTrace();
		}

		return referencias;
	}

	private ArrayList<Autor> getReferenceAuthors(int _refId) {
		String select = "select * from \"referencia_autor\" where id_referencia = '"
				+ _refId + "'";

		
		ArrayList<Autor> autores = new ArrayList<Autor>();
		try {
			ResultSet res = Database.getDatabaseInstance().doSelect(select);
			
			
			while (res.next()) {
				autores.add(getAuthorById(res.getInt("id_autor")));
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}

		return autores;
	}
	
	private Autor getAuthorById(int _authorId) {
		String select = "select * from \"autor\" where id = '" + _authorId + "'";
		Autor autor = new Autor();
		try {
			ResultSet res = Database.getDatabaseInstance().doSelect(select);
						
			if (res.next()) {
				autor.setNome(res.getString("nome"));
				autor.setEmail(res.getString("email"));
				autor.setId(res.getInt("id"));
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return autor;
	}

	/*
	 * Remove uma referência pelo seu id
	 */
	public void removeReferencia(Referencia ref) {
		// PersistenceManager pm = getPersistenceManager();
		/*
		 * try { long deleteCount = 0; Query q = pm.newQuery(Referencia.class,
		 * "id == i"); q.declareParameters("int i"); List<Referencia> references
		 * = (List<Referencia>) q.execute(ref .getId()); for (Referencia
		 * reference : references) { if (reference.getId() == ref.getId()) {
		 * deleteCount++; pm.deletePersistent(ref); } } if (deleteCount != 1) {
		 * LOG.log(Level.WARNING, "removeStock deleted " + deleteCount +
		 * " Stocks"); } } finally { pm.close(); }
		 */
	}

	private void salvaAutores(Referencia ref) throws SQLException {
		ResultSet res;
		if (ref.getAutores() != null && ref.getAutores().size() > 0) {
			for (Autor autor : ref.getAutores()) {
				Integer idAutor = autor.getId();
				
				//se a id do autor passada é nula, temos que achar ou criar esse autor no banco
				if (idAutor == null){
					// primeiro procura por autor ja inserido, para ver se já
					// existe...
					res = Database.getDatabaseInstance().doSelect(
							"select \"id\" from \"autor\" where \"nome\" ='"
									+ autor.getNome() + "'");

				
					// se o autor existe,
					if (res.next()) {
						idAutor = res.getInt("id");
					// se nao existe o autor, insere primeiro no banco
					} else {
						idAutor = Database.getDatabaseInstance().insert("autor",
								"\"nome\"", "'" + autor.getNome() + "'", "id");
					}
				}
				
				// insere a relacao autor X referencia
				Database.getDatabaseInstance().insert("\"referencia_autor\"",
						"\"id_autor\",\"id_referencia\"",
						idAutor + "," + ref.getId(), null);
			}
		}
	}

	public void updateReferencia(Referencia ref) {
		// PersistenceManager pm = getPersistenceManager();
		// ABRANG abr = ref.getAbrangencia();
		// int ano = ref.getAno();
		// ArrayList<Autor> autores = ref.getAutores();
		// Date dataPub = ref.getDataPub();
		// String local = ref.getLocal();
		// TYPE tipo = ref.getTipo();
		// TYPE_COMP_RES tipoCompRes = ref.getTipoCompRes();
		// TYPE_RESUMO tipoResumo = ref.getTipoResumo();
		// String titulo = ref.getTitulo();
		//
		// try {
		// pm.currentTransaction().begin();
		// //ref = pm.getObjectById(Referencia.class, ref.getId());
		// ref.setAbrangencia(abr);
		// ref.setAno(ano);
		// ref.setAutores(autores);
		// ref.setDataPub(dataPub);
		// ref.setLocal(local);
		// ref.setTipoCompRes(tipoCompRes);
		// ref.setTipoResumo(tipoResumo);
		// ref.setTitulo(titulo);
		// ref.setTipo(tipo);
		// pm.makePersistent(ref);
		// pm.currentTransaction().commit();
		// } catch (Exception ex) {
		// pm.currentTransaction().rollback();
		// throw new RuntimeException(ex);
		// } finally {
		// pm.close();
		// }
	}

}
